using Nop.Core;
using Nop.Core.Data;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Media;
using Nop.Services.Configuration;
using Nop.Services.Events;
using Nop.Services.Logging;
using Nop.Services.Media;
using ImageResizer;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Web;
namespace Nop.Plugin.Picture.CDN.Services
{
    public class CDNPictureService : PictureService, IPictureService
    {
        private static readonly object s_lock = new object();
        private readonly CDNPluginSettings _cdnPluginSettings;
        private readonly IRepository<Nop.Core.Domain.Media.Picture> _pictureRepository;
        private readonly IRepository<ProductPicture> _productPictureRepository;
        private readonly ISettingService _settingService;
        private readonly IWebHelper _webHelper;
        private readonly ILogger _logger;
        private readonly IEventPublisher _eventPublisher;
        private readonly MediaSettings _mediaSettings;
        public CDNPictureService(IRepository<Nop.Core.Domain.Media.Picture> pictureRepository, IRepository<ProductPicture> productPictureRepository, ISettingService settingService, IWebHelper webHelper, ILogger logger, IEventPublisher eventPublisher, MediaSettings mediaSettings, CDNPluginSettings cdnPluginSettings)
            : base(pictureRepository, productPictureRepository, settingService, webHelper, logger, eventPublisher, mediaSettings)
        {
            this._pictureRepository = pictureRepository;
            this._productPictureRepository = productPictureRepository;
            this._settingService = settingService;
            this._webHelper = webHelper;
            this._logger = logger;
            this._eventPublisher = eventPublisher;
            this._mediaSettings = mediaSettings;
            this._cdnPluginSettings = cdnPluginSettings;
        }
        #region  helper methods

        private string GetDomains()
        {
            string domainName = this._cdnPluginSettings.DomainNames;
            List<string> _domains = new List<string>();
            _domains = domainName.Split(new char[]
			{
				','
			}).ToList<string>();
            Random _random = new Random();
            string result;
            if (HttpContext.Current.Request.IsSecureConnection)
            {
                result = _domains.ElementAt(_random.Next(_domains.Count)).Replace("http://", "https://");
            }
            else
            {
                result = _domains.ElementAt(_random.Next(_domains.Count));
            }
            return result;
        }

        private string GetCDNDefaultPictureUrl(int targetSize = 0, PictureType defaultPictureType = PictureType.Entity)
        {
            string defaultImageFileName;
            switch (defaultPictureType)
            {
                case PictureType.Entity:
                    defaultImageFileName = _settingService.GetSettingByKey("Media.DefaultImageName", "default-image.gif");
                    break;
                case PictureType.Avatar:
                    defaultImageFileName = _settingService.GetSettingByKey("Media.Customer.DefaultAvatarImageName", "default-avatar.jpg");
                    break;
                default:
                    defaultImageFileName = _settingService.GetSettingByKey("Media.DefaultImageName", "default-image.gif");
                    break;
            }
            string cdnRelPath = string.Empty;
            // directly return the truth local default picture url without dynamic request.
            if (targetSize == 0)
            {
                // the cdn url is original url /i/default_avatar.jpg
                cdnRelPath = this.GetDomains() + "i/" + defaultImageFileName;
            }
            else
            {
                // the cdn url is /i/d/avatar_300/default-avatar.jpg
                var property = string.Format("{0}_{1}", defaultPictureType.ToString().ToLower(), targetSize);
                // for default picture if cache enabled directly return dynamic cdn picture url address.
                cdnRelPath = this.GetDomains() + string.Format("i/d/{0}/{1}", property, defaultImageFileName);
            }
            return cdnRelPath;
        }
        private string GetCDNPictureUrl(Nop.Core.Domain.Media.Picture picture, int targetSize = 0, bool showDefaultPicture = true, string storeLocation = null, PictureType defaultPictureType = PictureType.Entity)
        {
            var cdnUrl = string.Empty;
            if (picture == null)
            {
                if (showDefaultPicture)
                {
                    cdnUrl = GetDefaultPictureUrl(targetSize, defaultPictureType, storeLocation);
                }
                return cdnUrl;
            }
            string property = string.Empty;

            if (targetSize == 0)
            {
                property = picture.Id.ToString("0000000");
            }
            else
            {
                property = string.Format("{0}_{1}", picture.Id.ToString("0000000"), targetSize);
            }
            string seoFileName = picture.SeoFilename; // = GetPictureSeName(picture.SeoFilename); //just for sure
            string lastPart = GetFileExtensionFromMimeType(picture.MimeType);

            string virtualFilename = !String.IsNullOrEmpty(seoFileName) ?
                string.Format("i/d/{0}/{1}.{2}", property, seoFileName, lastPart) :
                string.Format("i/d/{0}.{1}", property, lastPart);

            cdnUrl = this.GetDomains() + virtualFilename;

            return cdnUrl;
        }
        private bool PictureCdnEnabled()
        {
            bool? cdnEnabled = new bool?(this._cdnPluginSettings.Enable);
            var isEnabled = cdnEnabled.HasValue && cdnEnabled == true;
            return isEnabled;
        }

        #endregion


        public override string GetDefaultPictureUrl(int targetSize = 0, PictureType defaultPictureType = PictureType.Entity, string storeLocation = null)
        {
            // CDN enbaled.
            if (PictureCdnEnabled())
            {
                return GetCDNDefaultPictureUrl(targetSize, defaultPictureType);
            }
            else
            {
                return base.GetDefaultPictureUrl(targetSize, defaultPictureType, storeLocation);
            }

        }

        public override string GetPictureUrl(
            Nop.Core.Domain.Media.Picture picture,
            int targetSize = 0,
            bool showDefaultPicture = true,
            string storeLocation = null,
            PictureType defaultPictureType = PictureType.Entity)
        {

            if (PictureCdnEnabled())
            {
                return GetCDNPictureUrl(picture, targetSize, showDefaultPicture, storeLocation);
            }
            else
            {
                return base.GetPictureUrl(picture, targetSize, showDefaultPicture, storeLocation, defaultPictureType);
            }
        }
    }
}
